/**
 ******************************************************************************
 * @file           : error_port.c
 * @brief          : Error Handler 平台适配层实现
 * @version        : 1.0.0
 * @date           : 2025-10-22
 ******************************************************************************
 * @note  移植层实现：根据实际平台提供时间戳和日志输出
 *        通过条件编译支持不同平台
 ******************************************************************************
 */

/* Includes ------------------------------------------------------------------*/
#include "error_port.h"
#include <stdio.h>

/* 平台检测和头文件包含 */
#if defined(STM32F0) || defined(STM32F030x6) || defined(STM32F030x8)
    #include "stm32f0xx_hal.h"
    #define ERROR_PORT_USE_STM32_HAL
#elif defined(STM32F1) || defined(STM32F103xB) || defined(STM32F103xE) || defined(STM32F10X_MD) || defined(STM32F10X_HD)
    #include "stm32f1xx_hal.h"
    #define ERROR_PORT_USE_STM32_HAL
#elif defined(STM32F2)
    #include "stm32f2xx_hal.h"
    #define ERROR_PORT_USE_STM32_HAL
#elif defined(STM32F3)
    #include "stm32f3xx_hal.h"
    #define ERROR_PORT_USE_STM32_HAL
#elif defined(STM32F4) || defined(STM32F407xx)
    #include "stm32f4xx_hal.h"
    #define ERROR_PORT_USE_STM32_HAL
#elif defined(STM32F7)
    #include "stm32f7xx_hal.h"
    #define ERROR_PORT_USE_STM32_HAL
#elif defined(STM32H7)
    #include "stm32h7xx_hal.h"
    #define ERROR_PORT_USE_STM32_HAL
#elif defined(STM32L0)
    #include "stm32l0xx_hal.h"
    #define ERROR_PORT_USE_STM32_HAL
#elif defined(STM32L1)
    #include "stm32l1xx_hal.h"
    #define ERROR_PORT_USE_STM32_HAL
#elif defined(STM32L4)
    #include "stm32l4xx_hal.h"
    #define ERROR_PORT_USE_STM32_HAL
#elif defined(STM32L5)
    #include "stm32l5xx_hal.h"
    #define ERROR_PORT_USE_STM32_HAL
#elif defined(STM32G0)
    #include "stm32g0xx_hal.h"
    #define ERROR_PORT_USE_STM32_HAL
#elif defined(STM32G4)
    #include "stm32g4xx_hal.h"
    #define ERROR_PORT_USE_STM32_HAL
#elif defined(STM32WB)
    #include "stm32wbxx_hal.h"
    #define ERROR_PORT_USE_STM32_HAL
#elif defined(STM32WL)
    #include "stm32wlxx_hal.h"
    #define ERROR_PORT_USE_STM32_HAL
#elif defined(USE_HAL_DRIVER)
    /* 通用HAL驱动：尝试自动包含 */
    #if __has_include("stm32f1xx_hal.h")
        #include "stm32f1xx_hal.h"
    #elif __has_include("stm32f4xx_hal.h")
        #include "stm32f4xx_hal.h"
    #endif
    #define ERROR_PORT_USE_STM32_HAL
#endif

/* FreeRTOS 环境 */
#if defined(USING_FREERTOS)
    #include "FreeRTOS.h"
    #include "task.h"
#endif

/* RT-Thread 环境 */
#if defined(USING_RTTHREAD) || defined(RT_USING_RTTHREAD)
    #include <rtthread.h>
#endif

/* ESP32 环境 */
#if defined(ESP_PLATFORM) || defined(ESP32)
    #include "freertos/FreeRTOS.h"
    #include "freertos/task.h"
    #include "esp_timer.h"
#endif

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/

#if defined(ERROR_PORT_BAREMETAL)
/* 
 * 裸机环境：系统滴答计数器
 * 用户需要在SysTick中断或定时器中断中递增此变量
 */
extern volatile uint32_t g_system_tick_ms;  /* 在main.c或其他文件中定义 */
#endif

/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/

/**
 * @brief       获取当前时间戳（毫秒）
 *
 * @param       无
 *
 * @retval      uint32_t: 当前时间戳（毫秒）
 *
 * @note        根据不同平台返回时间戳
 *              - STM32 HAL: HAL_GetTick()
 *              - FreeRTOS: xTaskGetTickCount() * portTICK_PERIOD_MS
 *              - 裸机: 用户提供的 g_system_tick_ms
 */
uint32_t Error_Port_GetTick(void)
{
#if defined(ESP_PLATFORM) || defined(ESP32)
    /* ESP32环境：使用esp_timer获取微秒级时间戳 */
    return (uint32_t)(esp_timer_get_time() / 1000);
    
#elif defined(USING_FREERTOS)
    /* FreeRTOS环境 */
    return (uint32_t)(xTaskGetTickCount() * portTICK_PERIOD_MS);
    
#elif defined(USING_RTTHREAD) || defined(RT_USING_RTTHREAD)
    /* RT-Thread环境：使用rt_tick_get()获取滴答数 */
    return (uint32_t)(rt_tick_get() * 1000 / RT_TICK_PER_SECOND);
    
#elif defined(ERROR_PORT_USE_STM32_HAL)
    /* STM32 HAL环境（自动检测） */
    return HAL_GetTick();
    
#elif defined(ERROR_PORT_BAREMETAL)
    /* 裸机环境：使用用户提供的滴答计数器 */
    return g_system_tick_ms;
    
#else
    /* 未定义平台：返回0（需要用户自行适配） */
    #warning "Error_Port_GetTick() not implemented for this platform"
    return 0;
#endif
}

/**
 * @brief       输出日志字符串
 *
 * @param[in]   str: 日志字符串
 *
 * @retval      无
 *
 * @note        根据不同平台输出日志
 *              - 有printf: 使用printf输出
 *              - 无printf: 可以通过UART或其他方式输出
 *              - 不需要: 实现为空函数
 */
void Error_Port_Print(const char *str)
{
#if defined(ERROR_PORT_DISABLE_PRINT)
    /* 禁用日志输出（节省资源） */
    (void)str;
    
#elif defined(ESP_PLATFORM) || defined(ESP32)
    /* ESP32环境：使用ESP_LOGI或printf */
    printf("%s", str);
    
#elif defined(USING_RTTHREAD) || defined(RT_USING_RTTHREAD)
    /* RT-Thread环境：使用rt_kprintf */
    rt_kprintf("%s", str);
    
#elif defined(USING_FREERTOS)
    /* FreeRTOS环境：可选添加互斥锁保护 */
    /* TODO: 如需线程安全，在此添加互斥锁 */
    // xSemaphoreTake(print_mutex, portMAX_DELAY);
    printf("%s", str);
    // xSemaphoreGive(print_mutex);
    
#else
    /* 默认：使用printf输出 */
    printf("%s", str);
#endif
}

/**
 * @brief       移植层初始化（可选）
 *
 * @param       无
 *
 * @retval      无
 *
 * @note        用于初始化平台相关资源
 *              如果不需要初始化，可以实现为空函数
 *              
 *              示例：
 *              - 初始化UART用于日志输出
 *              - 创建FreeRTOS互斥锁
 *              - 初始化系统滴答计数器
 */
void Error_Port_Init(void)
{
    /* 根据需要实现平台初始化 */
    
#if defined(ERROR_PORT_BAREMETAL)
    /* 裸机环境示例：配置SysTick为1ms */
    /*
    SysTick_Config(SystemCoreClock / 1000);
    */
#endif

#if defined(USING_FREERTOS)
    /* FreeRTOS环境示例：创建互斥锁 */
    /*
    print_mutex = xSemaphoreCreateMutex();
    */
#endif
}
